/*
 @Name: select插件
 @Author: ray
 @License: MIT
*/
; rayui.define(function (exports, undef) {
    "use strict";

    var $ = rayui.$,
        plugName = "select",
        $win = $(window),
        $doc = $(document),
        globalOptions = {
            maxHeight: 240,
            animSpeed: 200//动画执行时间
        },
        dict = { X: -1 },
        defSelectClass = "select-default",
        treeSelectClass = "tree-selected",
        wrapClass = "rayui-select-wrap",
        mainSelector = '.rayui-select-box>.select-tree',
        isDocBindMouseEvent = false,
        showTree = function () {
            //隐藏其他所有
            rayui.toggleDocEvt();
            //判断上面显示还是下面显示
            var $this = $(this),
                $title = $this.find(".select-title"),
                $tree = $this.find(".select-tree"),
                dataTreeHeight = $tree.outerHeight(),
                titleHeight = $title.outerHeight(),
                blowHeight = $win.height() + $win.scrollTop() - $title.offset().top - titleHeight;
            if (blowHeight < dataTreeHeight) {
                //上面显示
                $this.addClass("select-up");
            } else {
                $this.removeClass("select-up");
            }

            $tree.slideDown(globalOptions.animSpeed, function () {
                $this.addClass("select-expand");
                $title.find("input").focus();
            });
        },
        hideTree = function () {
            var $this = $(this),
                $tree = $(this).find(".select-tree");
            $this.removeClass("select-expand");
            //$tree.slideUp(globalOptions.animSpeed);
            $tree.css("display", "");
        },
        createDom = function ($parent, search, skin) {
            var optW = $parent.attr("option-width"),
                $main = $('<div class="rayui-select-box rayui-select-panel"' + (skin ? " skin=" + skin : "") + '/>').insertAfter($parent),
                $title = $('<div class="select-title"><div class="select-value"/></div>').appendTo($main),
                $select = $('<div class="select-tree"></div>').appendTo($main);
            
            $parent.hasClass(wrapClass) && $main.addClass(wrapClass);
            optW && $select.css({ width: optW });

            search && $('<input class="rayui-input select-input" placeholder="关键词"/>').appendTo($title);
            $title.append('<span class="select-arrow"><i class="ra ra-arrow-down"></i></span>');
            $select.append('<div class="tree-data-panel" style="max-height:' + globalOptions.maxHeight + 'px;"><ul class="select-ul"/></div>');

            return $main;
        },
        event = function ($main, isfromUl) {
            var $selectData = $main.find(".select-tree"),
                $prev = $main.prev(),
                $input = $main.find(".select-title>input"),
                $value = $main.find(".select-title>.select-value"),
                multiSelect = $prev.attr("multiple"),
                defval,
                $elem = isfromUl ? $prev.prev() : $prev,
                defaultText = $elem.find('option[value=""],li[value=""]').html() || "";

            //默认值和点击事件
            if (multiSelect) {
                var selectValues = [],
                    selectTextes = [],
                    getArray = function (data, attr) {
                        var str = [];
                        $.each($(data), function (a, b) {
                            str.push(attr ? $(b).attr(attr) : $(b).text());
                        });
                        return str;
                    },
                    setSelect = function () {
                        $value.html("").removeClass(defSelectClass);
                        isfromUl ? $prev.html("") : $prev.find("option:selected").prop("selected", false);
                        //给ul设置选中值
                        isfromUl && $elem.data("selected", selectValues);
                        $.each(selectValues, function (a, b) {
                            isfromUl ? $prev.append('<option value="' + b + '" selected></option>') :
                                $prev.find('option[value="' + b + '"]').prop("selected", true);
                            $value.append('<span class="tree-one-value">' + selectTextes[a] + '<span class="tree-value-del" value="' + b + '"><i class="ra ra-wrong"></i></span></span>');
                        });
                        if (selectValues.length === 0 && defaultText !== "") {
                            $value.html(defaultText).addClass(defSelectClass);
                        }
                    };
                //设置默认显示值样式，模拟滚动条
                $value.height($value.parent().height() + 20)
                    .css("overflow-x", "auto")
                    .on("mousedown." + plugName, function (e) {
                        dict.$elem = $(this);
                        dict.move = true;
                        dict.X = e.clientX;
                        dict.needStop = false;
                        dict.left = $(this).scrollLeft();
                    }).on("click." + plugName, function (e) {
                        //如果是滚动则阻止冒泡
                        if (dict.needStop) e.stopPropagation();
                    });
                if (!isDocBindMouseEvent) {
                    isDocBindMouseEvent = true;
                    $doc.on("mousemove." + plugName, function (e) {
                        if (dict.move) {
                            Math.abs(e.clientX - dict.X) > 5 && (dict.needStop = true);
                            dict.$elem.scrollLeft(dict.X - e.clientX + dict.left);
                        }
                    }).on("mouseup." + plugName, function () {
                        dict.move = false;
                    });
                }
                //点击事件
                $selectData.on('click.' + plugName, 'li:not(".rayui-disabled,.' + defSelectClass + '")', function (e) {
                    var value = $(this).attr("value") || "",
                        html = $(this).html(), selected;
                    e.stopPropagation();
                    if ($(this).hasClass(treeSelectClass)) {
                        //删除
                        selected = false;
                        $(this).removeClass(treeSelectClass);
                        var index = selectValues.indexOf(value);
                        if (index > -1) {
                            selectValues.splice(index, 1);
                            selectTextes.splice(index, 1);
                        }
                    } else {
                        //选中
                        selected = true;
                        $(this).addClass(treeSelectClass);
                        selectValues.push(value);
                        selectTextes.push(html);
                    }
                    setSelect();

                    $main.data("selected", selected).data("values", selectValues).data("textes", selectTextes);

                });
                //多选标签的删除事件
                $value.on("click." + plugName, ".tree-value-del", function (e) {
                    e.stopPropagation();
                    var val = $(this).attr("value");
                    $selectData.find("li[value=" + val + "]").click();
                    setSelect();
                });
                //多选设置默认选中
                if (isfromUl) {
                    defval = $elem.data("selected") || function () {
                        var $selectedLis = $elem.find("li[selected]");
                        if ($selectedLis.length === 0) return null;
                        return getArray($selectedLis, "value");
                    }();
                } else {
                    defval = $prev.val();
                }
                //defval可能值：null，数组
                var hasClicked = false;
                $.each(defval, function (a, b) {
                    if (b === "") return true;
                    $selectData.find('li[value="' + b + '"]').click();
                    hasClicked = true;
                });
                !hasClicked && setSelect();
            } else {
                //点击事件
                $selectData.on('click.' + plugName, 'li:not(".rayui-disabled")', function () {
                    var value = $(this).attr("value") || "",
                        html = $(this).html();

                    $selectData.find("." + treeSelectClass).removeClass(treeSelectClass);
                    $(this).addClass(treeSelectClass);

                    $prev.val(value);
                    isfromUl && $elem.data("selected", value);
                    $value.html(html);
                    
                    hideTree.call($main);
                    if (value === "") {
                        $value.addClass(defSelectClass);
                    } else {
                        $value.removeClass(defSelectClass);
                    }
                });

                //单选设置默认选中
                defval = isfromUl ? ($elem.data("selected") || $elem.find("li[selected]").attr("value") || "") : $prev.val();
                $selectData.find('li[value="' + defval + '"]:first').click();//添加first避免value值相同导致的多次click
            }

            //展开折叠
            $main.on("click." + plugName, '.select-title', function (e) {
                if ($main.hasClass("select-expand")) {
                    hideTree.call($main);
                } else {
                    showTree.call($main);
                }
                e.stopPropagation();
            });
            //input过滤
            if ($input) {
                $input.on("keyup." + plugName, function () {
                    var inputVal = $(this).val(),
                        $lis = $selectData.find("li");
                    inputVal === "" ? $lis.removeClass("hidden") : $lis.addClass("hidden");

                    $lis.not(".rayui-disabled").each(function () {
                        if ($(this).text().indexOf(inputVal) >= 0)
                            $(this).removeClass("hidden");
                    });
                }).on("click." + plugName, function(e) { e.stopPropagation(); });
            }
            //阻止冒泡
            $main.click(function (e) { e.stopPropagation(); });
        },
        renderSelect = function (container) {
            //初始化select
            var $objs = container ? $("select.rayui-select", container) : $("select.rayui-select");
            $objs.each(function () {
                var $this = $(this),
                    skin = $this.attr("skin"),
                    isRender = $this.data("render"),
                    search = $this.attr("rayui-search") !== undef;

                if (isRender) $this.next().remove();
                $this.data("render", true);
                var $main = createDom($this, search, skin),
                    $ul = $main.find(".select-tree .select-ul"),
                    searchOptions = function (dom, $parent) {
                        $(dom).children().each(function (a, b) {
                            var $this = $(b), isOptgp = b.nodeName === "OPTGROUP";
                            if (isOptgp) {
                                $([
                                    '<li class="select-item-label rayui-disabled',
                                    '"',//end class
                                    '>',
                                    $this.attr("label"),
                                    '</li>'
                                ].join('')).appendTo($parent);
                                $ul.addClass("select-group");
                                searchOptions(b, $parent);
                            } else {
                                var val = b.getAttribute("value") || "", classes = [];
                                val === "" && classes.push(" " + defSelectClass);
                                b.hasAttribute("disabled") && classes.push(" rayui-disabled");
                                $parent.append('<li class="' + classes.join('') + '" value="' + val + '">' + $this.html() + '</li>');
                            }
                        });
                    };

                $this.hasClass("full-width") && $main.addClass("full-width");
                searchOptions($this, $ul);
                event($main);
            });
        },
        renderSelectUl = function (container) {
            //初始化select ul
            var $objs = container === undef ? $("ul.rayui-select") : $("ul.rayui-select", container);
            $objs.each(function () {
                var $this = $(this),
                    skin = $this.attr("skin"),
                    isRender = $this.data("render"),
                    name = $this.attr("name"),
                    rayevent = $this.attr("ray-event"),
                    multiple = $this.attr("multiple"),
                    search = $this.attr("rayui-search") !== undef;

                if (isRender) {
                    $this.next().remove();
                    $this.next().remove();
                }
                $this.data("render", true);

                var $select = $(multiple ?
                    '<select class="hidden" name="' + name + '"></select>' :
                    '<input type="hidden" name="' + name + '"/>').insertAfter($this),
                    $main = createDom($select, search, skin),
                    $ul = $main.find(".select-tree .select-ul"),
                    searchOptions = function (dom, $parent) {
                        $(dom).children().each(function (a, b) {
                            var $this = $(b), isLabel = $(b).attr("label");
                            if (isLabel) {
                                $([
                                    '<li class="select-item-label rayui-disabled',
                                    '"',//end class
                                    '>',
                                    isLabel,
                                    '</li>'
                                ].join('')).appendTo($parent);
                                $ul.addClass("select-group");
                                searchOptions($(b).find("ul"), $parent);
                            } else {
                                var val = $this.attr("value") || "",
                                    classes = [];

                                val === "" && classes.push(defSelectClass);
                                b.hasAttribute("disabled") && classes.push(" rayui-disabled");
                                $parent.append('<li class="' + classes.join('') + '" value="' + val + '">' + $this.html() + '</li>');
                            }
                        });
                    };

                $this.hasClass("full-width") && $main.addClass("full-width");
                rayevent && $select.attr("ray-event", rayevent);
                multiple && $select.prop("multiple", true);
                searchOptions($this, $ul);
                event($main, true);
            });
        };

    var select = {
        on: function (event, callback, container) {
            if (event !== "select" || typeof callback !== "function") return this;
            container = container || "body";
            //$main阻止了冒泡
            $(container).find(mainSelector).on("click." + plugName, 'li:not(".rayui-disabled")', function () {
                var $this = $(this),
                    $main = $this.closest(".rayui-select-box"),
                    $elem = $main.prev(),
                    multiSelect = $elem.attr("multiple");

                //排除多选默认值
                if (multiSelect && $this.hasClass(defSelectClass)) return;

                var rayevent = $elem.attr("ray-event"),
                    value = $this.attr("value") || "",
                    html = $this.html();

                if(!rayevent) return;

                if (multiSelect) {
                    callback.call(this, {
                        isSingle: false,
                        event: rayevent,
                        elem: $elem,
                        value: value,
                        html: html,
                        selected: $main.data("selected"),
                        values: $main.data("values"),
                        textes: $main.data("textes")
                    });
                } else {
                    callback.call(this, {
                        isSingle: true,
                        event: rayevent,
                        elem: $elem,
                        value: value,
                        html: html
                    });
                }
            });
			return this;
        },
        off: function (event, container) {
            if (event !== "select") return this;
            container = container || "body";
            $(container).find(mainSelector).off("click." + plugName, selector);
			return this;
        },
        //select：select， ul：select ul (li标签需要写value属性)
        render: function (type, container) {
            if (type === "select") {
                renderSelect(container);
            } else if (type === "ul") {
                renderSelectUl(container);
            } else {
                renderSelect(container);
                renderSelectUl(container);
            }
        }
    };

    !rayui.selecttree && rayui.bindDocEvt(plugName, function () {
        $(".select-expand .select-tree").css("display", "");
        $(".select-expand").removeClass("select-expand");
    });

    exports(plugName, select);
}, rayui.jsAsync());
